package au.com.bus4u.shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Shiro框架配置类
 * 教程链接
 *  https://www.bilibili.com/video/av40342174?p=6
 */
@Configuration
public class ShiroConfig {

    @Value("${spring.profiles.uploads}")
    private String uploads;//图片访问路径
    /**
     * 创建ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

//        shiroFilterFactoryBean.setLoginUrl("/login.html");
        shiroFilterFactoryBean.setLoginUrl("/login.html");//修改跳转的登陆页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth.html");//设置未授权跳转页面

        /**
         *  添加Shiro内置过滤器：实现权限相关的拦截
         *  常用的过滤器：
         *      anon：无需认证（无需登陆）可以访问
         *      authc：必须认证才可以访问
         *      user：如果使用remenberMe的功能可以直接访问
         *      perms：必须授予资源权限才可以访问
         *      role：必须得到角色权限才可以访问
         */
        Map<String, String> filterMap = new LinkedHashMap<String, String>();

        filterMap.put("/static/**", "anon");// 静态资源全部放行 配置不会被拦截的链接 顺序判断
        filterMap.put("/validationUserEmail/**", "anon");// 静态资源全部放行 配置不会被拦截的链接 顺序判断
        filterMap.put("/"+uploads+"**", "anon");// 静态资源全部放行 配置不会被拦截的链接 顺序判断
        filterMap.put("/uploads/**", "anon");// 静态资源全部放行 配置不会被拦截的链接 顺序判断
        filterMap.put("/login.html", "anon");// 静态资源全部放行 配置不会被拦截的链接 顺序判断
        filterMap.put("/pc/user/login","anon");//不需要拦截的资源

        // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterMap.put("/logout", "logout");//退出后跳转到根目录“/”

        //filterMap.put("/home/cashier.html", "perms[user:add]");//退出后跳转到根目录“/”


        //过滤链定义，从上向下顺序执行，一般将 /**放在最为下边 -->:这是一个坑呢，一不小心代码就不好使了
        filterMap.put("/", "authc");
        filterMap.put("/index", "authc");
        filterMap.put("/index.html", "authc");
        filterMap.put("/admin/**", "authc");
        filterMap.put("/pc/index.html", "authc");//通配方式拦截所有资源(需登陆才能访问)
        filterMap.put("/pc/home/**", "authc");//通配方式拦截所有资源(需登陆才能访问)
        filterMap.put("/home/**", "authc");//通配方式拦截所有资源(需登陆才能访问)
        filterMap.put("/order/**", "authc");//通配方式拦截所有资源(需登陆才能访问)
        filterMap.put("/auction/**", "authc");//通配方式拦截所有资源(需登陆才能访问)



        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);


        return shiroFilterFactoryBean;
    }



    /**
     *  创建DefaultWebSecurityManager
     */
    @Bean(name="securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联Realm
        securityManager.setRealm(userRealm);

        return securityManager;
    }

    /**
     *
     * 创建Realm
     */
    @Bean(name="userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }



    /**
     * 配置ShiroDialect，用于thymeleaf和shiro标签配合使用
     */
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }





    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    /**
     *  开启shiro aop注解支持.
     *  使用代理方式;所以需要开启代码支持;
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}
